require "test/unit/testcase"

module Test
  module Unit
    module AssertionsWithDiff
      def assert_equal(expected, actual, message=nil)
        super
      rescue AssertionFailedError
        expected = PP.pp(expected, "") unless expected.is_a?(String)
        actual = PP.pp(actual, "") unless actual.is_a?(String)
        diff = Diff.readable(expected, actual)
        if /^[\?\-\+].{79}/ =~ diff
          folded_diff = Diff.readable(fold(expected), fold(actual))
          diff = "#{diff}\n\nfolded diff:\n#{folded_diff}"
        end
        raise $!, "#{$!.message}\n\ndiff:\n#{diff}", $@
      end

      def fold(string)
        string.split(/\n/).collect do |line|
          line.gsub(/(.{78})/, "\\1\n")
        end.join("\n")
      end
    end

    module AdditionalAssertions
      def assert_boolean(expected)
        assert([true, false].include?(expected),
               build_message(nil,
                             "<true or false> expected but was\n<?>",
                             expected))
      end
    end

    class TestCase
      include AssertionsWithDiff
      include AdditionalAssertions
    end
  end
end
